package com.cc.util;

import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;

public class FileUtil {
    private static final Logger logger = Logger.getLogger(FileUtil.class);

    // 配置化的上传路径前缀
    private static final String UPLOAD_PATH_PREFIX = "/upload";

    // 允许的文件扩展名
    private static final Set<String> ALLOWED_EXTENSIONS = Set.of("jpg", "jpeg", "png", "gif");

    // 最大文件大小（5MB）
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;

    public static String getImgUrl(HttpServletRequest request, Part part) {
        try {
            // 获取文件名
            String fileName = part.getSubmittedFileName();
            if (fileName == null || fileName.isEmpty()) {
                throw new IllegalArgumentException("文件名为空");
            }

            // 校验文件名是否合法
            if (!isValidFileName(fileName)) {
                throw new IllegalArgumentException("非法文件名：" + fileName);
            }

            // 校验文件类型
            if (!isValidFileType(fileName)) {
                throw new IllegalArgumentException("不支持的文件类型：" + fileName);
            }

            // 校验文件大小
            if (part.getSize() > MAX_FILE_SIZE) {
                throw new IllegalArgumentException("文件大小超出限制：" + part.getSize() + "字节");
            }

            // 指定上传路径
            String realPath = request.getServletContext().getRealPath(UPLOAD_PATH_PREFIX);
            if (realPath == null) {
                throw new IllegalStateException("无法获取上传路径");
            }

            // 构建完整的上传目录路径
            File uploadDir = new File(realPath);
            if (!uploadDir.exists() && !uploadDir.mkdirs()) {
                throw new IOException("无法创建上传目录：" + uploadDir.getAbsolutePath());
            }

            // 重命名文件以避免冲突
            String uniqueFileName = UUID.randomUUID().toString().substring(0, 8) + "_" + fileName;
            File uploadedFile = new File(uploadDir, uniqueFileName);

            // 将文件上传到服务器
            try (InputStream input = part.getInputStream()) {
                Files.copy(input, uploadedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }

            // 记录成功日志
            logger.debug("文件上传成功：文件名=" + uniqueFileName + ", 文件大小=" + part.getSize() + "字节");

            // 返回文件的访问路径
            return UPLOAD_PATH_PREFIX + "/" + uniqueFileName;

        } catch (IOException e) {
            logger.error("文件写入失败：" + e.getMessage());
            throw new RuntimeException("文件写入失败，请检查服务器权限或磁盘空间", e);
        } catch (IllegalArgumentException | IllegalStateException e) {
            logger.error("文件上传参数错误：" + e.getMessage());
            throw e;
        }
    }

    /**
     * 校验文件名是否合法，防止路径遍历攻击
     */
    private static final Pattern FILE_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\-\\.]+$");

    private static boolean isValidFileName(String fileName) {
        return fileName != null && FILE_NAME_PATTERN.matcher(fileName).matches();
    }

    /**
     * 校验文件类型是否允许
     */
    private static boolean isValidFileType(String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        return ALLOWED_EXTENSIONS.contains(extension);
    }
}